/*-------------------------------------------------------------------------
***************** Modification History ***********************************
   @doc
   @module ui.c - User Interface functionality |
   @end
   
$Log: /SoftPay/SPK2SIM/Source/Ui/ui.c $ 
**************************************************************************

   Copyright (C) 1999 by VeriFone, Inc.

   All rights reserved.  No part of this software may be reproduced,
   transmitted, transcribed, stored in a retrieval system, or translated
   into any language or computer language, in any form or by any means,
   electronic, mechanical, magnetic, optical, chemical, manual or otherwise,
   without the prior written permission of VeriFone, Inc.

---------------------------------------------------------------------------*/
#define VSUI_C

#include <project.h>

//#include <beetle.h>
//#include <beetleplug.h>

#include <aclconio.h>
#include <acldev.h>
#include <aclstr.h>
#include <message.h>
#include <applidl.h>
#include <svctxo.h>
#include <svc.h>
#include <string.h>
#include <power.h>

/** /#define DEBUG_VSUI*/ 

#ifdef DEBUG_VSUI
#define DEBUG_95
#endif

#include <define.h>
#include <tct.h>
#include <lct.h>
#include <tblutil.h>
#include <msg.h>
#include <msgfuncs.h>
#include <entry.h>
#include <init.h>
#include <card.h>
#include <util.h>
#include <date.h>
#include <format.h>
#include <logo.h>
#include <ui.h>
#include <spdebug.h>
#include <multilng.h>
#include <gds.h>
#include <codesec.h>


#define TITLE_LINE_380      1
#define TITLE_LINE_390      1
#define STATUS_LINE_380     1
#define STATUS_LINE_390     4
#define MESSAGE_SIZE_392   20


extern int inImamLineNumber;

typedef struct tagFontInfo {
    char fiROMName[9];
    char fiPageName[9];
    char fiWidth;
    char fiHeight;
    char fiGridSetting;
    char fiReserved[3];
} FontInfo;

DisplayObject obDisp;

/*-------------------------------------------------------------------------
    Function :
    Description :
    Parameters :
    Returns :
    Globals :
    Notes :
    Modification History :
      #     Date      Who                     Description
    ----- -------- ---------- ---------------------------------------------

--------------------------------------------------------------------------*/
void vdClearNonTitleLines() {
    int inLeft,
    inTop,
    inRight,
    inBottom;
    int inDummyX1 = 1,
    inY1 = (obDisp.inTitleLine + 1),
    inX2 = inGetRowLim(),
    inY2 = obDisp.inCharsPerColumn;

    wherewin(&inLeft, &inTop, &inRight, &inBottom);
    if (!obDisp.blActionFontASC8x21) {
        vdCalculateCoord(GRID_4x8_TO_8x21, &inDummyX1, &inY1);
        --inY1;
        vdCalculateCoord(GRID_4x8_TO_8x21, &inX2, &inY2);
    }

    vdClear_8X21_Window(obDisp.inHomeCol, inY1, inX2, inY2);
    window(inLeft, inTop, inRight, inBottom);
}

/*-------------------------------------------------------------------------
    Function :    vdClearTitleLine
    Description : Clears the first line on the display
    Parameters :
    Returns :
    Globals :
    Notes :
    Modification History :
      #     Date      Who                     Description
    ----- -------- ---------- ---------------------------------------------

--------------------------------------------------------------------------*/
void vdClearTitleLine() {
    int inLeft,
    inTop,
    inRight,
    inBottom;
    int inDummyX1 = 1,
    inY1 = (obDisp.inTitleLine),
    inY2 = (obDisp.inTitleLine),
    inX2 = inGetRowLim();

    wherewin(&inLeft, &inTop, &inRight, &inBottom);
    if (!obDisp.blActionFontASC8x21) {
        vdCalculateCoord(GRID_4x8_TO_8x21, &inDummyX1, &inY1);
        vdCalculateCoord(GRID_4x8_TO_8x21, &inX2, &inY2);
    }
    vdClear_8X21_Window(obDisp.inHomeCol, inY1, inX2, inY2);
    window(inLeft, inTop, inRight, inBottom);
}


/*-------------------------------------------------------------------------
    Function :    vdClearLogoLine
    Description : Clears the first line on the display
    Parameters :
    Returns :
    Globals :
    Notes :
    Modification History :
      #     Date      Who                     Description
    ----- -------- ---------- ---------------------------------------------

--------------------------------------------------------------------------*/
void vdClearLogoLine(void) {
    int inLeft,
    inTop,
    inRight,
    inBottom,
    inGrid;

    wherewin(&inLeft, &inTop, &inRight, &inBottom);
    inGrid = getgrid();

    if (inGrid == 0) // 16x16 or 8x16 font
        window(1, 1, 16, 1);
    else // 6x8 font
        window(1, 1, 16, 2);

    clrscr();
    window(inLeft, inTop, inRight, inBottom);
}



/*-------------------------------------------------------------------------
    Function :    vdClearASCII8x21Window(int inXL, int inYL, int inXR, int inYR)
    Description : Clears a window based on the 8x21 grid
    Parameters :
    Returns :
    Globals :
    Notes :
    Modification History :
      #     Date      Who                     Description
    ----- -------- ---------- ---------------------------------------------

--------------------------------------------------------------------------*/
void vdClearASCII8x21Window(int inXL,int inYL,int inXR,int inYR) {
    int inLeft,
    inTop,
    inRight,
    inBottom,
    inGrid;
    char szFontName[FILENAME_SIZE + 1];

    wherewin(&inLeft, &inTop, &inRight, &inBottom);
    vdValidateWindowCoords(GRID_8X21, &inXL, &inYL, &inXR, &inYR);
    inGrid = getgrid();

    if (inGrid == 0) // 16x16 or 8x16 font
    {
        get_font(szFontName);
        set_font(ASC8X21_VFT);
        window(inXL, inYL, inXR, inYR);
        clrscr();
        set_font(szFontName);
    } else // Already in 8x21 mode
    {
        window(inXL, inYL, inXR, inYR);
        clrscr();
    }
    window(inLeft, inTop, inRight, inBottom);
}


/*-------------------------------------------------------------------------
    Function    :vdValidateWindowCoords (int inGridType, int inXL, int inYL, 
                                         int inXR, int inYR)
    Description : Validates the window cordinates for each grid
    Parameters  : Grid type and the coordinates
    Returns     : NIL
    Globals     : NIL
    Notes       :
    Modification History :
      #     Date      Who                     Description
    ----- -------- ---------- ---------------------------------------------

--------------------------------------------------------------------------*/
void vdValidateWindowCoords(int inGridType,int* pinXL,int* pinYL,int* pinXR,int* pinYR) {
    if (*pinXL < 1)
        *pinXL = 1;
    if (*pinXR < 1)
        *pinXR = 1;
    if (*pinYR < 1)
        *pinYR = 1;
    if (*pinYL < 1)
        *pinYL = 1;

    switch (inGridType) {
    case GRID_8X21:
        if (*pinXL > 21)
            *pinXL = 21;
        if (*pinXR > 21)
            *pinXR = 21;
        if (*pinYR > 8)
            *pinYR = 8;
        if (*pinYL > 8)
            *pinYL = 8;
        break;
    case GRID_4X16:
        if (*pinXL > 16)
            *pinXL = 16;
        if (*pinXR > 16)
            *pinXR = 16;
        if (*pinYR > 4)
            *pinYR = 4;
        if (*pinYL > 4)
            *pinYL = 4;
        break;
    case GRID_4X8:
        if (*pinXL > 8)
            *pinXL = 8;
        if (*pinXR > 8)
            *pinXR = 8;
        if (*pinYR > 4)
            *pinYR = 4;
        if (*pinYL > 4)
            *pinYL = 4;
        break;
    default:
        break;
    }
}


/*-------------------------------------------------------------------------
    Function :  void vdClearStatusMessage()
    Description :
    Parameters :
    Returns :
    Globals :
    Notes :
    Modification History :
      #     Date      Who                     Description
    ----- -------- ---------- ---------------------------------------------

--------------------------------------------------------------------------*/
void vdClearStatusMessage() {
    int inLeft,
    inTop,
    inRight,
    inBottom;
    int inDummyX1 = 1,
    inY1 = (obDisp.inStatusLine),
    inY2 = (obDisp.inStatusLine),
    inX2 = inGetRowLim();

    wherewin(&inLeft, &inTop, &inRight, &inBottom);
    if (!obDisp.blActionFontASC8x21) {
        vdCalculateCoord(GRID_4x8_TO_8x21, &inDummyX1, &inY1);
        vdCalculateCoord(GRID_4x8_TO_8x21, &inX2, &inY2);
    }
    vdClear_8X21_Window(obDisp.inHomeCol, inY1, inX2, inY2);
    window(inLeft, inTop, inRight, inBottom);
}

/*-------------------------------------------------------------------------
    Function : inDisplayResponseString
    Description : Displays Response message from the host and allows the 
                  user to scroll through it if longer than the screen length
    Parameters : pchDispMsg = pointer to the message being displayed
    Returns : 
    Globals :
    Notes : 

    Modification History :
      #     Date      Who                     Description
    ----- -------- ---------- ---------------------------------------------
      0   12/09/96  Donncha_H1                Creation
      1   01/14/96  Donncha_H1  Increased size of display buffer
--------------------------------------------------------------------------*/
void vdDisplayResponseString(char* pchDispMsg) {
    char szTempDispStr[HF_BRSP_MSG_SIZE + HF_BRSP_CODE_SIZE + 1];
    VS_BOOL fExitFunction = VS_TRUE;
    int inCharOffset = 0,
    inKeyPress;

    //pdebug(("--vdDisplayResponseString--"));

    if (strlen(pchDispMsg) <= (unsigned) obDisp.inCharsPerRow)
        vdDisplayErrorString(pchDispMsg);
    else {
        // BT_TRACE ('I', pchDispMsg);
        vdStrNoCpy(szTempDispStr, pchDispMsg, sizeof(szTempDispStr));
        vdBeep();

        do {
            vdDisplayAt(obDisp.inHomeCol, obDisp.inStatusLine, szTempDispStr + inCharOffset, CLR_EOL);
            vdFlushKeyboardBuffer();
            inKeyPress = get_char();
            if (inKeyPress == KEY_STR) {
                if (inCharOffset > 0)
                    inCharOffset--;
                fExitFunction = VS_FALSE;
            } else if (inKeyPress == KEY_PND) {
                fExitFunction = VS_FALSE;
                if ((unsigned) inCharOffset < strlen(szTempDispStr) - obDisp.inCharsPerRow)
                    inCharOffset++;
            } else
                fExitFunction = VS_TRUE;
        } while (fExitFunction == VS_FALSE);
    }   /* else */
}

/*-------------------------------------------------------------------------
    Function :    vdDispStrCentered
    Description : Displays a string right justified
    Parameters :
    Returns :
    Globals :
    Notes :
    Modification History :
      #     Date      Who                     Description
    ----- -------- ---------- ---------------------------------------------
      0   08/17/95  Ana_C1    Created.
--------------------------------------------------------------------------*/
void vdDispStrCentered(char* pchInStr,int inYCord,int inClearDp) {
    int inXCord,
    x1,
    x2,
    y1,
    y2;

    //pdebug(("--vdDispStrCentered--")); 

    wherewin(&x1, &y1, &x2, &y2);
    inXCord = (x2 - x1 - strlen(pchInStr) + 2) / 2;
    vdDisplayAt(inXCord, inYCord, pchInStr, inClearDp);
}

/*-------------------------------------------------------------------------
    Function :    vdDispStrAtRight
    Description : Displays a string right justified
    Parameters :
    Returns :
    Globals :
    Notes :
    Modification History :
      #     Date      Who                     Description
    ----- -------- ---------- ---------------------------------------------
      0   08/17/95  Ana_C1    Created.
--------------------------------------------------------------------------*/
void vdDispStrAtRight(char* pchInStr,int inYCord,int inClearDp) {
    int inXCord,
    x1,
    x2,
    y1,
    y2,
    inLength;

    //pdebug(("--vdDispStrAtRight--"));

    wherewin(&x1, &y1, &x2, &y2);

    inLength = inXCord = x2 - x1 - inMLstrlen(pchInStr) + 2;
    vdDisplayAt(inXCord, inYCord, pchInStr, inClearDp);
}



void vdDisplayString(const char* szMessage) {
    int inLeft,
    inTop,
    inRight,
    inBottom;
    int inRowLim = inGetRowLim();
    int inDispRow = obDisp.inInputLine;

    //pdebug(("--vdDisplayString--"));
    wherewin(&inLeft, &inTop, &inRight, &inBottom);

    window(obDisp.inHomeCol, obDisp.inTitleLine, inRowLim, inDispRow);
    vdScrollDataEntry(!obDisp.blNoScrollEntries);
    vdDisplayAt(obDisp.inHomeCol, inDispRow, szMessage, CLR_EOL);

    window(inLeft, inTop, inRight, inBottom);
}

void vdDisplayErrorString(const char* szErrorString) {
    //pdebug(("--vdDisplayErrorString--"));
    vdDisplayAt(obDisp.inHomeCol, obDisp.inStatusLine, szErrorString, CLR_EOL);
    // load_keypad(2,0,0);  //Done for Enabling the keyboard on any error message
    vdBeep();
    vdFlushKeyboardBuffer();
	//inWaitKey(5); // : display error msg, wait for 3 second
    inWaitKey(inGetIdleTimeOut());
}

void vdDisplayWarningString(const char* szString) {
    int inLeft,
    inTop,
    inRight,
    inBottom;
    int inRowLim = inGetRowLim();

    wherewin(&inLeft, &inTop, &inRight, &inBottom);
    window(obDisp.inHomeCol, obDisp.inStatusLine, inRowLim, obDisp.inCharsPerColumn);
    vdDisplayAt(obDisp.inHomeCol, obDisp.inStatusLine, szString, CLR_EOL);
    vdWarnBeep();
    vdDelay(ERR_MSG_DELAY);
    window(inLeft, inTop, inRight, inBottom);
}

void vdDisplayStatusString(const char* szString) {
    vdDisplayAt(obDisp.inHomeCol, obDisp.inStatusLine, szString, CLR_EOL);
}

/* Displays a message from the index with coordinates */
void vdDispMsgAt(long lnMsgIdx,int inXCord,int inYCord,int inClearDp) {
    char szMsg[MESSAGE_SIZE + 1];

    *szMsg = NULL_CH;
    vdGetMessageFromFile(lnMsgIdx, szMsg);
    if (*szMsg == NULL_CH)
        strcpy(szMsg, "Bad Msg ID");

    vdDisplayAt(inXCord, inYCord, szMsg, inClearDp);
}

/*-------------------------------------------------------------------------
    Function :    vdDispWarningMsg
    Description : Displays a warning message.
    Parameters :
    Returns :
    Globals :
    Notes :
    Modification History :
      #     Date      Who                     Description
    ----- -------- ---------- ---------------------------------------------
      1   09/18/96 Donncha_H1                 Creation
--------------------------------------------------------------------------*/
void vdDisplayWarningMsg(long lnMsgIdx) {
    char szMsg[MESSAGE_SIZE + 1];

    *szMsg = NULL_CH;
    vdGetMessageFromFile(lnMsgIdx, szMsg);
    if (*szMsg == NULL_CH)
        strcpy(szMsg, "BAD Msg ID");

    vdDisplayWarningString(szMsg);
}

/*-------------------------------------------------------------------------
    Function :    vdDispMsgCentered
    Description : Displays a message centered.
    Parameters :
    Returns :
    Globals :
    Notes :
    Modification History :
      #     Date      Who                     Description
    ----- -------- ---------- ---------------------------------------------
      0   06/29/95  Henry_G1   Created.
--------------------------------------------------------------------------*/
void vdDispMsgCentered(long lnMsgIdx,int inYCord,int inClearDp) {
    char szMsg[MESSAGE_SIZE + 1];

    *szMsg = NULL_CH;
    vdGetMessageFromFile(lnMsgIdx, szMsg);
    if (*szMsg == NULL_CH)
        strcpy(szMsg, "BAD Msg ID");

    vdDispStrCentered(szMsg, inYCord, inClearDp);
}

/*-------------------------------------------------------------------------
    Function :    vdDispMsgAtRight
    Description : Displays a message from the index right justified
    Parameters :
    Returns :
    Globals :
    Notes :
    Modification History :
      #     Date      Who                     Description
    ----- -------- ---------- ---------------------------------------------
      0   06/29/95  Henry_G1   Created.
      1   08/17/95  T_Al_G     Changed to use new vdDispStrAtRight() function.
      2   08/30/95  T_Al_G     Fixed bug in call to vdDispStrAtRight().
      3   11/13/96  Page_K1    Delay if obDisp.inTitleLine == obDisp.inInputLine
--------------------------------------------------------------------------*/
void vdDispMsgAtRight(long lnMsgIdx,int inYCord,int inClearDp) {
    char szMsg[MESSAGE_SIZE + 1];

    *szMsg = NULL_CH;
    vdGetMessageFromFile(lnMsgIdx, szMsg);
    if (*szMsg == NULL_CH)
        strcpy(szMsg, "BAD Msg ID");

    vdDispStrAtRight(szMsg, inYCord, inClearDp);
}

void vdDisplayTitle(long lnTitle,int inJustify) {
    //pdebug(("--vdDisplayTitle--"));
    //pdebug(("inTitle = %d", inTitle));
    //pdebug(("inJustify = %d", inJustify));

    switch (inJustify) {
    case LEFT_JUSTIFY:
        vdDispMsgAt(lnTitle, obDisp.inHomeCol, obDisp.inTitleLine, NO_CLEAR);
        break;
    case CENTER_JUSTIFY:
        vdDispMsgCentered(lnTitle, obDisp.inTitleLine, NO_CLEAR);
        break;
    case RIGHT_JUSTIFY:
        vdDispMsgAtRight(lnTitle, obDisp.inTitleLine, NO_CLEAR);
        break;
    case CLEAR_TITLE:
        vdDispMsgAt(lnTitle, obDisp.inHomeCol, obDisp.inTitleLine, CLR_EOL);
        break;
    }

    if (obDisp.inTitleLine == obDisp.inStatusLine || obDisp.inTitleLine == obDisp.inInputLine)
        vdDelay(PROMPT_DELAY);
}

/*--------------------------------------------------------------------------
    Function :  vdDispFormattedAmt()
    Description : Displays formatted amount
    Parameters :
    Returns :
    Globals :
    Notes :
    Modification History :
      #     Date      Who                     Description
    ----- -------- ---------- ---------------------------------------------
      1   09/08/96 Donncha_H1                Creation
      2   10/11/96 Donncha_H1 For a non O470 terminal now always display 
--------------------------------------------------------------------------*/
void vdDispFormattedAmt(char* pchAmt,long  lnMsgNum,int  inLnNum) {
    char szTempAmt[AMT_SIZE + 1];
    int inLeft,
    inTop,
    inRight,
    inBottom,
    inGrid;
    char szFontName[FILENAME_SIZE + 1];


    strcpy(szTempAmt, pchAmt);
    vdFormatAmount(szTempAmt, VS_TRUE);
    vdDispMsgAt(lnMsgNum, obDisp.inHomeCol, inLnNum, CLR_EOL);

    inGrid = getgrid();
    if (inGrid == 0) // 16x16 or 8x16 font
    {
        wherewin(&inLeft, &inTop, &inRight, &inBottom);
        get_font(szFontName);
        set_font(ASC8X21_VFT);
        inLnNum *= 2; // converting the line number to the 8x21 mode
        vdDisplayDataStr(szTempAmt, inLnNum, NO_CLEAR, ML_RIGHT);
        set_font(szFontName);
        window(inLeft, inTop, inRight, inBottom);
    } else
        vdDispStrAtRight(szTempAmt, inLnNum, NO_CLEAR);
}

/*--------------------------------------------------------------------------
    Function :  vdDispSettleMsg()
    Description : Displays settlement msg for the 470 and waits for either
                  2 secs or for a key-press before returning
    Parameters :  pchMessage
    Returns :     
    Globals :
    Notes :
    Modification History :
      #     Date      Who                     Description
    ----- -------- ---------- ---------------------------------------------
      1   09/17/96 Donncha_H1                Creation
--------------------------------------------------------------------------*/
void vdDispSettleMsg(char* szMsg) {
    unsigned long ulTimer;

    vdDisplayStatusString(szMsg);
    ulTimer = set_itimeout(NO_CLOCK_HANDLE PROMPT_DELAY_SECONDS, TM_SECONDS);
    while (!KBHIT() && CHECK_TIMEOUT(ulTimer) > 0)
    ;
    clrscr();
}


/*-------------------------------------------------------------------------
    Function :    vdDisplayTranTitle
    Description : Displays the txn type on the top right of the screen
    Parameters :  inTitle = the message number to display
    Returns :
    Globals :     
    Notes :
    Modification History :
      #     Date      Who                     Description
    ----- -------- ---------- ---------------------------------------------
      0   01/09/96 Donncha_H1                Creation
      1   01/14/98 Kevin_V1   Modified to use SPA_MESSAGE_FILE.
      2   01/29/98 Betty_B1   Modified the window func to use '1'
                              instead of CDT_CLABEL_SIZE+2
      
--------------------------------------------------------------------------*/
void vdDisplayTranTitle(long lnTitle) {
    char szMsg[MESSAGE_SIZE + 1];
    int inLeft,
    inTop,
    inRight,
    inBottom;
    int inRowLim = inGetRowLim();

    //pdebug(("--vdDisplayTranTitle--"));

    wherewin(&inLeft, &inTop, &inRight, &inBottom);
    *szMsg = NULL_CH;
    vdGetMessageFromFile(lnTitle, szMsg);
    if (*szMsg == NULL_CH)
        strcpy(szMsg, "BAD Msg ID");

    if (obDisp.inTitleLine == obDisp.inStatusLine || obDisp.inTitleLine == obDisp.inInputLine)
        clrscr();

    window(obDisp.inHomeCol, obDisp.inTitleLine, inRowLim, obDisp.inTitleLine);
    //clreol();

    if (strlen(szMsg) > (unsigned) obDisp.inCharsPerRow - (CLABEL_SIZE + 2) && !(obDisp.inTitleLine == obDisp.inStatusLine || obDisp.inTitleLine == obDisp.inInputLine))
        vdDisplayAt(obDisp.inHomeCol, obDisp.inTitleLine, szMsg, /*NO_CLEAR*/CLR_EOL);
    else {
        /* Always appears at left on 3200 */
        vdDisplayAt(obDisp.inHomeCol, obDisp.inTitleLine, szMsg, /*NO_CLEAR*/CLR_EOL);
    }

    window(inLeft, inTop, inRight, inBottom);

    if (obDisp.inTitleLine == obDisp.inStatusLine || obDisp.inTitleLine == obDisp.inInputLine)
        vdDelay(PROMPT_DELAY);
}

/*-------------------------------------------------------------------------
    Function :    vdDisplayScrollItem
    Description : 
    Returns :     
    Globals :
    Notes : 
    Modification History :
      #     Date      Who                     Description
    ----- -------- ---------- ---------------------------------------------
--------------------------------------------------------------------------*/

void vdDisplayScrollItem(char* szText,UINT uiStartDelayMs,UINT uiScrollDelayMs,VS_BOOL fAllowKeyAbort,int inStopIndex) {
    int inTextLength = strlen(szText);
    int inDWidth = obDisp.inCharsPerRow;
    int inOffset = 1;
    char szDBuf[MAX_CHARS_PER_ROW + 1];

    memset(szDBuf, 0, sizeof(szDBuf));
    strlcpy(szDBuf, szText, inDWidth);
    vdDisplayStatusString(szDBuf);
    SVC_WAIT(uiStartDelayMs);

    if ((inTextLength - inDWidth) > 0)
        while (inOffset < (inTextLength - inStopIndex)) {
            memset(szDBuf, 0, sizeof(szDBuf));
            strlcpy(szDBuf, szText + inOffset, inDWidth);
            vdDisplayStatusString(szDBuf);
            SVC_WAIT(uiScrollDelayMs);
            ++inOffset;
            if (KBHIT() && fAllowKeyAbort)
                break;
        }

    return;
}

void vdValidateFontFileNames(void) {
    char szFontName[FILENAME_SIZE + 1]; 

    /*
     *      This function sets Display Object flags for the Action &
     *      Menu Fonts to prevent unnecessary Font switching
     */
    strcpy(szFontName, STATIC_DATA_PATH);
    strcpy(&szFontName[strlen(szFontName)], szGetActionFontName());
    strupr(szFontName); 
    obDisp.blActionFontASC8x21 = VS_TRUE;  
    if (strcmp(szFontName, ENTRY_FONT) != 0)
        obDisp.blActionFontASC8x21 = VS_FALSE;  

    strcpy(szFontName, STATIC_DATA_PATH);
    strcpy(&szFontName[strlen(szFontName)], szGetMenuFontName());
    strupr(szFontName); 
    obDisp.blMenuFontASC4x16 = VS_TRUE;  
    if (strcmp(szFontName, IDLE_FONT) != 0)
        obDisp.blMenuFontASC4x16 = VS_FALSE;
}

/*-------------------------------------------------------------------------
    Function :    vdInitDisplay()
    Description :
    Parameters :
    Returns :
    Globals :
    Notes :
    Modification History :
    #     Date      Who                     Description
  ----- -------- ---------- ---------------------------------------------
    0    06/29/98 Kevin_V1  Initial code write.
--------------------------------------------------------------------------*/
void vdInitDisplay() {
    obDisp.inTerminalType = TERMINAL_OMNI_3200;

    obDisp.blNoScrollEntries = VS_FALSE;

    obDisp.inPrevLangIndex = inGetLanguageIdx();
    obDisp.blCurrBigFontOn = TRUE;
    obDisp.blPrevBigFontOn = TRUE; /* ML #9 check ! */

    obDisp.lastX1 = 1;
    obDisp.lastY1 = 1;
    obDisp.lastX2 = 21;
    obDisp.lastY2 = 8;
    obDisp.chCaratOffset = uiDOWN_ARROW;

    obDisp.blCfigEdit = VS_FALSE;
    obDisp.blOptActive = VS_FALSE;
    obDisp.blEntryNextLine = VS_FALSE;
    obDisp.blNextLineCleanup = VS_FALSE;
    obDisp.blCaratVis = VS_TRUE;    
    obDisp.blActionFontASC8x21 = VS_TRUE;     
    obDisp.blMenuFontASC4x16 = VS_TRUE;
    obDisp.inMinPWLength = 1;

    vdValidateFontFileNames();

    /*
     * demo msg used in idle loop;
     * add blank to center exactly
     */
    obDisp.szDemoMsg[0] = ' '; obDisp.szDemoMsg[1] = NULL_CH;
    strncat(obDisp.szDemoMsg, pchGetMessage(IDLE_DEMO_MSG), (sizeof(obDisp.szDemoMsg) - 2));
    obDisp.szDemoMsg[(sizeof(obDisp.szDemoMsg) - 1)] = NULL_CH;

    /*
     * locked msg used in idle loop;
     * do not add blank to center....
     */
    vdUpdateKbdStatusMsg();

    /*
     * setup the display-obj functions
     */
    obDisp.vdDO_idle_logo = idle_logo_default;
    obDisp.inDO_ChooseOne = inChooseOneDefault;
    obDisp.vdDO_UpdateMenu = vdUpdateMenu;

    // Choose One Hot Key Support
    obDisp.lnChooseOneHotKeys = 0L;

    vdSetActionFont();
}

void vdUpdateKbdStatusMsg(void) {
    obDisp.szLockedMsg[0] = NULL_CH;
    strncpy(obDisp.szLockedMsg, pchGetMessage(KBD_LOCKED_MSG), (sizeof(obDisp.szLockedMsg) - 1));
    obDisp.szLockedMsg[(sizeof(obDisp.szLockedMsg) - 1)] = NULL_CH;
}




void vdDisplayAt(int x,int y,const char* m,int o) {
    if (strlen(m) > 0)
        display_at((UINT) x, (UINT) y, (char *) m, (UINT) o);
    else {
        if ((o == CLR_EOL) || (o == CLR_LINE)) {
            if ((getgrid() == 0) && (get_font_mode() == 2)) // 2 byte addressing scheme + 16x16 Font
                display_at((UINT) x, (UINT) y, "\x01\x20", (UINT) o);
            else
                display_at((UINT) x, (UINT) y, " ", (UINT) o);
        }
    }
}

int inMessageLength(long lnMessageNumber) {
    char szMessage[MESSAGE_SIZE + 1];
    int inStringLength = 0;

    //pdebug(("--inMessageLength(%d)--", lnMessageNumber));
    *szMessage = NULL_CH;
    vdGetMessageFromFile(lnMessageNumber, szMessage);
    if (*szMessage != NULL_CH)
        inStringLength = strlen(szMessage);

    return (inStringLength);
}

void vdWarnBeep() {
    int inCount;

    for (inCount = 0; inCount < 3; inCount++) {
        vdBeep();
    }
}

void vdBeep(void) {
    vdDelay(BEEP_DELAY);
    error_tone();
}

/******************************************************************************
 *                          Keyboard related functions.                       *
 ******************************************************************************/
char szKeyMap[MAX_ALPNUM_KEYS][CHAR_PER_KEY] = {
    "0- +&",
    "1QZqz.\\",
    "2ABCabc~",
    "3DEFdef%",
    "4GHIghi@",
    "5JKLjkl/",
    "6MNOmno?",
    "7PRSprs[",
    "8TUVtuv]",
    "9WXYwxy{",
    "*,'\"}",
    "#=:$^"
};

char chGetAlphaKey(char chKey) {
    char* chPtr;
    int inIndex;

    for (inIndex = 0; inIndex < MAX_ALPNUM_KEYS; inIndex++) {
        chPtr = (char *) strchr((char *) szKeyMap[inIndex], (int) chKey);
        if (chPtr != NULL_CH) {
            if (*++chPtr == '\0')
                chPtr = szKeyMap[inIndex];
            return(*chPtr);
        }
    }
    return(0);
}

/* Flushes the keyboard buffer by reading and ignoring all keys buffered */
void vdFlushKeyboardBuffer() {
    //pdebug(("--vdFlushKeyboardBuffer--"));

    KBHIT();        /* Don't ask why just trust that a lot of */
    /* time was wasted tracking this down     */
    if (get_console(0) >= 0)
        while (KBHIT())
            get_char();//if
}

void vdInitCharacterSet() {
#ifdef  NEW_CODE
    KeyboardInfo.inNumberOfRegularKeys = SVC_INFO_KEY(0);
    KeyboardInfo.inNumberOfScreenKeys = SVC_INFO_KEY(2);
    KeyboardInfo.inNumberOfNonScreenKeys = SVC_INFO_KEY(1);
#endif
}


/*-------------------------------------------------
 Test whether a card is swiped, data entered through keypad or the clear key pressed.
--------------------------------------------------*/
int inWaitForUser() {
    int inResult = 0;
    unsigned long ulTimerCount;

    ulTimerCount = set_itimeout(NO_CLOCK_HANDLE inGetIdleTimeOut(), TM_SECONDS);
    while (!inResult) {
        //****** BRG 10/06/99
        // gu_clr_state, no longer exists in ACT2000 - see ACTPORTSRS.DOC
        //      if (gu_clr_state)
        //          inResult = 3;
        //****** BRG 10/06/99 END 
        if (CHK_CARD_RDR())
            inResult = 1;
        if (KBHIT())
            inResult = 2;
        if (CHECK_TIMEOUT(ulTimerCount) == 0)
            inResult = 4;
    }
    return(inResult);
}

int inWaitKeyWithBeep(int inSeconds,int intDelayBeep) {
    unsigned long ulTimerCount;
    unsigned long ulDelayBeep;

    //pdebug(("--inWaitKeyWithBeep--"));

    do {
        ulTimerCount = set_itimeout(NO_CLOCK_HANDLE inSeconds, TM_SECONDS);
        ulDelayBeep = set_itimeout(NO_CLOCK_HANDLE intDelayBeep, TM_SECONDS);

        while (CHECK_TIMEOUT(ulTimerCount) != 0) {
            if (KBHIT() != 0)
                return(get_char());
            if (inSeconds >= intDelayBeep) {
                if (CHECK_TIMEOUT(ulDelayBeep) == 0) {
                    vdBeep();
                    vdDelay(150);
                }
            }
        }

        // KV1 20010105 - Allow terminal to go to sleep
        if (srGDS.fHandHeld && srGDS.fBatteryOperated && get_dock_status() == HANDHELD_UNDOCKED) {
            vdTerminalSleep(); 
        } else {
            break;
		}
    } while (VS_TRUE);

    return(KEY_CANCEL);
}

/*
 * returns any key pressed that is pressed in a particular delay, if no key
 * is pressed in the specified duration, returns CLEAR_KEY (27). 
 */
#ifdef IMAM_NO_SLEEP
int inWaitKey(int inSeconds) 
{
    unsigned long ulTimerCount;
    if (KBHIT()) get_char();

    ulTimerCount = set_itimeout(NO_CLOCK_HANDLE inSeconds, TM_SECONDS);
       
    while (CHECK_TIMEOUT(ulTimerCount) != 0){
		if (KBHIT() != 0)
			return(get_char());
    }
    return(KEY_CANCEL);
}

#else
int inWaitKey(int inSeconds) {
    //    unsigned long ulTimerCount;
    int inTimeout = 0;
    long lnEvent = 0;
    int inTimer = 0;

    //pdebug(("--inWaitKey--"));

    // Key Waiting? (KV1 14-NOV-01)
    if (KBHIT())
        return(get_char());

    do {
        /* Set the required timeout before we start */
        inTimer = set_timer((long) inSeconds * 1000, EVT_TIMER);

        /* THIS IS IF SOFTPAY IS THE ONLY APPLICATION !!!!! */
        lnEvent = 0;
        while (((lnEvent & EVT_KBD) == 0) && ((lnEvent & EVT_TIMER) == 0)) {
            /* THIS IS IF SOFTPAY IS THE ONLY APPLICATION !!!!! */
            lnEvent = wait_event();
        }

        /* Clear any existing timer */
        clr_timer(inTimer);

#if 0
        ulTimerCount = set_itimeout(NO_CLOCK_HANDLE inSeconds, TM_SECONDS);
       
        while (CHECK_TIMEOUT(ulTimerCount) != 0)
        {
            if (KBHIT() != 0)
                return(get_char());
        }
#endif

        if (lnEvent & EVT_KBD)
            return(get_char());

        // KV1 20010105 - Allow terminal to go to sleep
        if (srGDS.fHandHeld && srGDS.fBatteryOperated && get_dock_status() == HANDHELD_UNDOCKED){
            vdTerminalSleep(); 
		}else {
            break;
		}
    } while (VS_TRUE);

    //NKJT gu_clr_state = TRUE;
    return(KEY_CANCEL);
}
#endif

/*-----------------------------------------------------------------------------
* Routine Name : vdPrepareXXXLineChoice()
* Description  : For all display types other than 1X16.
*                This function takes a message from the message file and
*                formats it into a buffer to indicate the screen addressable
*                keys that may be chosen. Two to four choices in the message 
*                are allowed. The message must be in the following format:
*                          "choi1~choi2~choi3~choi"
*                and each choice must be separated by a ~. The choice can be 
*                up to 5 characters (anything more is truncated).
* Parameters   : pchMessageFile = pointer to the required message file string
*                inMsgIdx = Message Index into message file
*                inNbrChoices = Number of Choices on the display to choose
*                pchBuf1 = pointer to first display buffer
*                pchBuf2 = pointer to second display buffer
* Returns      : 
* Notes        : 
* Modification History :
*    #     Date      Who                     Description
*  ----- -------- ---------- ---------------------------------------------
*    0      ?         ?      Creation.
*    1   10/15/96 Pat_G1     Removed pchMessageFile. Changed inMsgIdx to
*                            pchChoiceMsg.
*-----------------------------------------------------------------------------
*/
void vdPrepareXXXLineChoice(char* pchChoiceMsg,int inNbrChoices,char* pchDispBuf1) {
    char szMsg2[MESSAGE_SIZE + 1];
    char szInvalidMessageID[10 + 1];
    int inOffset0 = 1;
    int inOffset1 = (obDisp.inCharsPerRow / 4) + inOffset0;
    int inFldWidth = inOffset1 - inOffset0;
    int inSeparPos = 0,
    inTmpSepPos = 0,
    inPrmptNo;

    //pdebug(("--vdDispXXXLineChoice--"));
    //pdebug(("pchChoiceMsg %s", pchChoiceMsg ));

    if (pchChoiceMsg[0] == NULL_CH) {
        strcpy(szInvalidMessageID, "BAD Msg ID");    
        strlcpy(pchChoiceMsg, szInvalidMessageID, MESSAGE_SIZE);
        vdDisplayAt(1, obDisp.inStatusLine, pchChoiceMsg, CLR_EOL);
    } else {
        if (inNbrChoices == 2)
            vdStrNoCpyChar(szMsg2, " ", inOffset1 + 1);
        else
            vdStrNoCpyChar(szMsg2, " ", inOffset0 + 1);

        for (inPrmptNo = 0; inPrmptNo < inNbrChoices; inPrmptNo++) {
            inSeparPos = inStrPos(pchChoiceMsg + inTmpSepPos, '~', strlen(pchChoiceMsg) - inTmpSepPos);
            if ((inSeparPos == -1) && (inPrmptNo < inNbrChoices - 1 || inSeparPos>(int)strlen(pchChoiceMsg))) {
                //pdebug(("Not enough Choice separators"));
                return;
            }

            vdFormatChoiceStr(szMsg2 + strlen(szMsg2), pchChoiceMsg + inTmpSepPos, MAX_CHOICE_PRMPT_SIZE + 1, inFldWidth); 
            inTmpSepPos += inSeparPos + 1;
        }
        vdStrNoCpy(pchDispBuf1, szMsg2, strlen(szMsg2));
    }
}


void vdPrepare3200LineChoice(char* pchChoiceMsg,int inNbrChoices,char pchDispBuf1[][MESSAGE_SIZE + 1]) {
    int inI,
    inResult;

    memset(pchDispBuf1, 0, ((MESSAGE_SIZE + 1) * inNbrChoices));
    if (*pchChoiceMsg)
        for (inI = 1; inI <= 4; ++inI) {
            if ((inResult = fieldvar(pchChoiceMsg, inI, '~', pchDispBuf1[inI - 1])) <= 0)
                break;
        }
}

/*-----------------------------------------------------------------------------
* Routine Name : vdCreateOptWin3200()
* Description  : Creates right-side screen-addressable-key
*                window display for omni 3200.
* Parameters   : szDispBuf = pointer to key-label string array.
* Returns      : void
* Notes        : 
* Modification History :
*    #     Date      Who                     Description
*  ----- -------- ---------- ---------------------------------------------
*    0   08/14/98 EW_1       Initial Code Write
*-----------------------------------------------------------------------------
*/
static char szDivider[2] = "|";

static void vdDisplayDivider(void) {
    int inRow;
    char* pszFontName = NULL_CH;
    char szFontName[FILENAME_SIZE + 1];

    vdGetCurrentFont(szFontName);
    strupr(szFontName);
    switch (obDisp.inCurFontType) {
    case GRID_4X8:
        pszFontName = ASC4X8_VFT;
        break;
    case GRID_4X16:
        pszFontName = ASC4X16_VFT;
        break;
    case GRID_8X21:
        pszFontName = ASC8X21_VFT;
        break;
    }

    /*
     *      Do not switch if corect font is already active
     */
    if (strcmp(szFontName, pszFontName) == 0)
        pszFontName = NULL_CH;

    if (pszFontName != NULL_CH) {
        setfont(pszFontName);   
        window(obDisp.in3200BarCol, obDisp.inTitleLine, obDisp.inCharsPerRow, obDisp.inCharsPerColumn);
    }

    for (inRow = 1; inRow <= obDisp.inCharsPerColumn; ++inRow) {
        vdDisplayAt(1, inRow, szDivider, NO_CLEAR);
		//if (inRow == 16) vdDisplayAt(1, inRow, szDivider, CLR_EOL);
    }



    if (pszFontName != NULL_CH)
        setfont(szFontName);
}

void vdCreateOptWin3200(char szDispBuf[][MESSAGE_SIZE + 1]) {
    int i,
    j,
    inInc,
    inMaxOptLength = 0,
    inLength;

    if (!obDisp.blOptActive) {
        obDisp.blOptActive = VS_TRUE; /* Creation; save prev */
        vdSaveDispObjWindow();
    }

    /*
     *      Compute Bar Column position by Max Option Length
     */
    for (i = 0; i < 4; ++i) {
        inLength = inMLstrlen(szDispBuf[i]);
        inMaxOptLength = (inLength > inMaxOptLength ? inLength : inMaxOptLength);
    }
    obDisp.in3200BarCol = obDisp.inCharsPerRow - inMaxOptLength;

    /*
     * Clear new Option Window
     */
    window(obDisp.in3200BarCol, obDisp.inTitleLine, obDisp.inCharsPerRow, obDisp.inCharsPerColumn); 
    clrscr();

    /*
     *      Choice text appears on rows 1,3,5,7 for 8x fonts, and 1,2,3,4 for 4x fonts
     */
	if (inImamLineNumber==16){
		inInc = 3;
		for (i = 1, j = 4; i <= obDisp.inCharsPerColumn; ++i, j += inInc) {
			if (j <= obDisp.inCharsPerColumn-3) {
				/* vdDisplayAt(2, j, szDispBuf[i-1], NO_CLEAR);*/
				vdDispStrAtRight(szDispBuf[i - 1], j, NO_CLEAR);
			}
		}
	} else {
		inInc = (obDisp.inCharsPerColumn == 4 ? 1 : 2);
		for (i = 1, j = 1; i <= obDisp.inCharsPerColumn; ++i, j += inInc) {
			if (j <= obDisp.inCharsPerColumn) {
				/* vdDisplayAt(2, j, szDispBuf[i-1], NO_CLEAR);*/
				vdDispStrAtRight(szDispBuf[i - 1], j, NO_CLEAR);
			}
		}
	}
    vdDisplayDivider();

    /*
     * leave only left-side active
     */
    window(obDisp.inHomeCol, obDisp.inTitleLine, (obDisp.in3200BarCol - 1), obDisp.inCharsPerColumn);
}

/*-----------------------------------------------------------------------------
* Routine Name : vdDestroyOptWin3200()
* Description  : Clears and removes right-side screen-addressable-key
*                window display for omni 3200.
* Parameters   : szDispBuf = pointer to key-label string array.
* Returns      : void
* Notes        : 
* Modification History :
*    #     Date      Who                     Description
*  ----- -------- ---------- ---------------------------------------------
*    0   08/14/98 EW_1       Initial Code Write
*-----------------------------------------------------------------------------
*/
void vdDestroyOptWin3200() {
    //pdebug (("--vdDestroyOptWin3200--"));
    if (obDisp.inTerminalType == TERMINAL_OMNI_3200) {
        if (obDisp.blOptActive) {
            /*
             *  activate right side
             */
            window(obDisp.in3200BarCol, obDisp.inTitleLine, obDisp.inCharsPerRow, obDisp.inCharsPerColumn); 

            clrscr();

            /*
             * restore window to whatever it was
             */

            //window(obDisp.lastX1, obDisp.lastY1, obDisp.lastX2, obDisp.lastY2);
            vdRestoreDispObjWindow();

            obDisp.blOptActive = VS_FALSE;  /* Destroyed; mark as such */
        }
    }
}

void vdSaveDispObjWindow() {
    //pdebug (("--vdSaveDispObjWindow--"));
    wherewin(&obDisp.lastX1, &obDisp.lastY1, &obDisp.lastX2, &obDisp.lastY2);
    //pdebug (("%d,%d,%d,%d",obDisp.lastX1, obDisp.lastY1, obDisp.lastX2, obDisp.lastY2));
}


void vdRestoreDispObjWindow() {
    //pdebug (("--vdRestoreDispObjWindow--"));
    //pdebug (("%d,%d,%d,%d",obDisp.lastX1, obDisp.lastY1, obDisp.lastX2, obDisp.lastY2));
    window(obDisp.lastX1, obDisp.lastY1, obDisp.lastX2, obDisp.lastY2);
}


/*-----------------------------------------------------------------------------
* Routine Name : vdPrepareOneLineChoice()
* Description  : For a Omni470 display (1X16).
*                This function takes a message from the message file and
*                formats it into either one or two buffers depending on if 
*                there are greater than two screen choices. The message must
*                be in the following format:
*                          "choi1~choi2~choi3~choi"
*                and each choice must be separated by a ~. The choice can be 
*                up to 5 characters (anything more is truncated).
* Parameters   : pchMessageFile = pointer to the required message file string
*                inMsgIdx = Message Index into message file
*                inNbrChoices = Number of Choices on the display to choose
*                pchBuf1 = pointer to first display buffer
*                pchBuf2 = pointer to second display buffer
* Returns      : 
* Notes        : 
* Modification History :
*    #     Date      Who                     Description
*  ----- -------- ---------- ---------------------------------------------
*    0     ?       ?         Creation
*    1   10/15/96 Pat_G1     Changed inMsgIdx to pchChoiceMsg. Removed 
*                            pchMessageFile.
*-----------------------------------------------------------------------------
*/
void vdPrepareOneLineChoice(char* pchChoiceMsg,int inNbrChoices,char* pchBuf1,char* pchBuf2) {
    int inOffset0 = 2;
    int inOffset1 = obDisp.inCharsPerRow / 2;
    int inFldWidth = inOffset1 - inOffset0;
    char szMsg2[DOUBLE_SIXTEEN_CHAR_DISP + 1];
    char szBuf[3 + 1];
    int inSeparPos = 0,
    inTmpSepPos = 0,
    inPrmptNo;

    //pdebug(("--vdPrepareOneLine--"));
    //pdebug(("pchChoiceMsg %s", pchChoiceMsg ));

    memset(szMsg2, '\0', sizeof(szMsg2));

    if ((strchr(pchChoiceMsg, '~')) == NULL_CH) {
        //pdebug(("No separator in string"));
        return;
    }

    if (strlen(pchChoiceMsg) == 0)
        return;

    strcpy(szBuf, "%d=");

    for (inPrmptNo = 0; inPrmptNo < inNbrChoices; inPrmptNo++) {
        if ((((inSeparPos = inStrPos(pchChoiceMsg + inTmpSepPos, '~', strlen(pchChoiceMsg) - inTmpSepPos)) == -1) && (inPrmptNo < inNbrChoices - 1)) || (inSeparPos > (int) strlen(pchChoiceMsg))) {
            //pdebug(("Not enough Choice separators"));
            return;
        }
        sprintf(szMsg2 + strlen(szMsg2), szBuf, inPrmptNo + 1);
        vdFormatChoiceStr(szMsg2 + strlen(szMsg2), pchChoiceMsg + inTmpSepPos, MAX_CHOICE_PRMPT_SIZE + 1, inFldWidth); 
        inTmpSepPos += inSeparPos + 1;
    }

    vdStrNoCpy(pchBuf2, szMsg2 + SIXTEEN_CHAR_PER_ROW, SIXTEEN_CHAR_PER_ROW);
    szMsg2[SIXTEEN_CHAR_PER_ROW] = '\0';
    vdStrNoCpy(pchBuf1, szMsg2, SIXTEEN_CHAR_PER_ROW);

    if (inNbrChoices <= 2)
        *pchBuf2 = NULL_CH;

    //pdebug(("pchBuf2=%s", pchBuf2));
    //pdebug(("pchBuf1=%s", pchBuf1));
}  


/*-----------------------------------------------------------------------------
* Routine Name : vdTimeAndDisplay()
* Description  : Displays on the status line for inTimeOut seconds the
*                string passed in, or until a key is pressed. 
*                
* Parameters   : pchDispBuf = pointer to buffer to display
*                inTimeOut  = Time duration in which to display message
* Returns      : 
* Notes        : 
* Modification History :
*    #     Date      Who                     Description
*  ----- -------- ---------- ---------------------------------------------
*    0      ?     Donncha_H1                Creation
*    1   02/13/97 Donncha_H1 Changed TM_SECONS to TM_TICKS - greater granularity
*-----------------------------------------------------------------------------
*/
void vdTimeAndDisplay(char* pchDispBuf,int inTimeOut) {
    unsigned long ulTimerCount;

    ulTimerCount = set_itimeout(NO_CLOCK_HANDLE inTimeOut, TM_TICKS);
    vdDisplayAt(obDisp.inHomeCol, obDisp.inStatusLine, pchDispBuf, CLR_EOL);
    for (; !KBHIT() && CHECK_TIMEOUT(ulTimerCount) > 0;)
        ;
}

/*-----------------------------------------------------------------------------
* Routine Name : inDisplayAndWaitChoice()
* Description  : Displays four strings that are being passed in for 
*                inLittleTimeOut seconds each. If a key-press occurs and it 
*                is not a # or * then the key-press value is returned. 
*                The # and * keys serve to scroll the first message if its length 
*                is greater than the chars per row. 
* Parameters   : pchDispBuf1 = pointer to first display buffer  
*                pchDispBuf2 = pointer to second display buffer
*                pchDispBuf3 = pointer to second display buffer
*                pchDispBuf4 = pointer to second display buffer
*                inBigTimeOut= num of seconds to wait for a key-press
*                inLittleTimeOut= pause between each prompt display
*                
* Returns      : CLEAR_KEY or inKeyPress
* Notes        : 
*      #     Date      Who                     Description
*    ----- -------- ---------- ---------------------------------------------
*       0   06/25/96  Donncha_H1    Created.
*       1   09/07/96  Donncha_H1 Pressing the # key at the end of the line
*                               does not cause the first display line to change
*-----------------------------------------------------------------------------
*/
int inDisplayAndWaitChoice(char* pchDispBuf1,char* pchDispBuf2,char* pchDispBuf3,char* pchDispBuf4,int  inBigTimeOut,int  inLittleTimeOut) {
    int inKeyPress,
    inCharOffset = 0;
    VS_BOOL fPrevNext = VS_FALSE,
    fExitFunction = VS_FALSE;
    unsigned long ulTimerCount1; 

    //pdebug(("--inDisplayAndWaitChoice--"));

    if (strlen(pchDispBuf1) > (unsigned) obDisp.inCharsPerRow)
        fPrevNext = VS_TRUE;
    do {
        ulTimerCount1 = set_itimeout(NO_CLOCK_HANDLE inBigTimeOut, TM_SECONDS);
        while ((CHECK_TIMEOUT(ulTimerCount1) > 0) && (KBHIT() == 0)) {
            if ((pchDispBuf1 != NULL_CH) && (KBHIT() == 0) && (ulTimerCount1 > 0) && (strlen(pchDispBuf1) > 0))
                vdTimeAndDisplay(pchDispBuf1 + inCharOffset, inLittleTimeOut);

            if ((pchDispBuf2 != NULL_CH) && (KBHIT() == 0) && (ulTimerCount1 > 0) && (strlen(pchDispBuf2) > 0))
                vdTimeAndDisplay(pchDispBuf2, inLittleTimeOut);

            if ((pchDispBuf3 != NULL_CH) && (KBHIT() == 0) && (ulTimerCount1 > 0) && (strlen(pchDispBuf3) > 0))
                vdTimeAndDisplay(pchDispBuf3, inLittleTimeOut);

            if ((pchDispBuf4 != NULL_CH) && (KBHIT() == 0) && (ulTimerCount1 > 0) && (strlen(pchDispBuf4) > 0))
                vdTimeAndDisplay(pchDispBuf4, inLittleTimeOut);
        }

        if (KBHIT() != 0) {
            inKeyPress = get_char();
            if (fPrevNext == VS_TRUE) {
                if ((inKeyPress == KEY_STR) && (inCharOffset > 0)) {
                    fExitFunction = VS_FALSE;
                    inCharOffset--;
                } else if (inKeyPress == KEY_PND) {
                    fExitFunction = VS_FALSE;
                    if ((unsigned) inCharOffset < strlen(pchDispBuf1) - obDisp.inCharsPerRow)
                        inCharOffset++;
                } else
                    return(inKeyPress);
            } else
                return(inKeyPress);
        } else
            fExitFunction = VS_TRUE;
    } while (fExitFunction == VS_FALSE);

    //****** BRG 10/06/99
    //gu_clr_state = TRUE;
    //****** BRG 10/06/99 END

    return(CLEAR_KEY);
}

/*-----------------------------------------------------------------------------
* Routine Name : vdDispMsgAndStr()
* Description  : This displays a string
*                
* Parameters   : 
*                
* Returns      : void
* Notes        : 
*
*    Modification History :
*    #     Date      Who                     Description
*  ----- -------- ---------- ---------------------------------------------
*     0 08/07/96  Donncha_H1               Created.
*-----------------------------------------------------------------------------
*/
void vdDispMsgAndStr(char* pchMessageFile,long lnMsgIdx,char* pchBuf,int inLineNo) {
    char szMsg[MESSAGE_SIZE + 1];
    char szInvalidMessageID[10 + 1];

    //pdebug(("--vdDispMsgAndStr--"));
    *szMsg = NULL_CH;
    vdGetMessageFromFile(lnMsgIdx, szMsg);

    if (*szMsg == NULL_CH) {
        strcpy(szInvalidMessageID, "BAD Msg ID");    
        vdStrNoCpy(szMsg, szInvalidMessageID, MESSAGE_SIZE);
        vdDisplayAt(obDisp.inHomeCol, inLineNo, szMsg, CLR_EOL);
    } else {
        vdStrNoCpy(szMsg + strlen(szMsg), pchBuf, MESSAGE_SIZE - strlen(szMsg));
        vdDisplayAt(obDisp.inHomeCol, inLineNo, szMsg, CLR_EOL);
    }
}

/*-------------------------------------------------------------------------
    Function :    inRotatingDisplayWait
    Description : It automatically scrolls the display.
    Parameters :  pchDispBuf  pointer to display buffer
    Returns :     
    Globals :
    Notes :
    Modification History :
      #     Date      Who                     Description
    ----- -------- ---------- ---------------------------------------------
      0   02/12/97 Donncha_H1                   Creation 
      1   05/28/98 Kevin_V1   Changed to support inWaitForUser() entries.
--------------------------------------------------------------------------*/
int inRotatingDisplayWait(char* pchDispBuf,int  inInputLine) {
    int inCharOffset = 0;
    int inLeft,
    inTop,
    inRight,
    inBottom;
    unsigned long ulTimerCount;
    int inResult = 0;
    int inRowLim = inGetRowLim();

    ulTimerCount = set_itimeout(NO_CLOCK_HANDLE inGetIdleTimeOut(), TM_SECONDS);

    //pdebug(("--inRotatingDisplayWait--"));

    wherewin(&inLeft, &inTop, &inRight, &inBottom);
    window(obDisp.inHomeCol, obDisp.inTitleLine, inRowLim, inInputLine);

    /* vdTimeAndDisplay(pchDispBuf+inCharOffset, PROMPT_DELAY_SCROLLING); */
    vdTimeAndDisplay(pchDispBuf + inCharOffset, DELAY_SCROLLING_TICKS);

    do {
        vdTimeAndDisplay(pchDispBuf + inCharOffset, DELAY_SCROLLING_TICKS);

        //****** BRG 10/06/99
        //if (gu_clr_state)
        //  inResult = 3;
        //****** BRG 10/06/99 END
        if (CHK_CARD_RDR())
            inResult = 1;

        if (KBHIT()) {
            inResult = 2;
            if (act_kbd_pending_test(KEY_CANCEL))
                inResult = VS_ESCAPE;
            vdFlushKeyboardBuffer();
        }

        if (CHECK_TIMEOUT(ulTimerCount) == 0)
            inResult = 4;

        if ((unsigned) inCharOffset < strlen(pchDispBuf) - obDisp.inCharsPerRow)
            inCharOffset++;
        else
            inCharOffset = 0;
    } while (inResult == 0);

    window(inLeft, inTop, inRight, inBottom);

    return inResult;
}


/*-------------------------------------------------------------------------
    Function :    vdLoad3200Opt
    Description : loads confedit keys for right-side display.
    Returns :     
    Globals :
    Notes :
    Modification History :
      #     Date      Who                     Description
    ----- -------- ---------- ---------------------------------------------
      0   08/17/98 EW_1       Creation 
--------------------------------------------------------------------------*/
void vdLoad3200Opt(char szLineBuf[][MESSAGE_SIZE + 1],long lnMsgId) {
    int inI,
    inResult;
    char sz3200Msg[MESSAGE_SIZE + 1];

    vdGetMessageFromFile(lnMsgId, sz3200Msg);
    memset(szLineBuf, 0, ((MESSAGE_SIZE + 1) * 4));
    if (*sz3200Msg)
        for (inI = 1; inI <= 4; ++inI) {
            if ((inResult = fieldvar(sz3200Msg, inI, '~', szLineBuf[inI - 1])) <= 0)
                break;
        }
}

/*-------------------------------------------------------------------------
    Function :    inGetRowLim
    Description : determines row limit for shared functions
    Returns :     rightmost column character for platform
    Globals :
    Notes : 
    Modification History :
      #     Date      Who                     Description
    ----- -------- ---------- ---------------------------------------------
      0   08/25/98 EW_1       Creation 
--------------------------------------------------------------------------*/
int inGetRowLim() {
    int inRowLim = obDisp.inCharsPerRow;

    if (obDisp.inTerminalType == TERMINAL_OMNI_3200) {
        if (obDisp.blOptActive)
            inRowLim = obDisp.in3200BarCol - 1;
    }
    return(inRowLim);
}


/*-------------------------------------------------------------------------
    Function :    vdScrollDataEntry
    Description : handles scrolling of data-input GRID_8X21 Display
    Returns :     
    Globals :
    Notes : 
    Modification History :
      #     Date      Who                     Description
    ----- -------- ---------- ---------------------------------------------
      0   08/25/98 EW_1       Creation 
--------------------------------------------------------------------------*/

void vdScrollDataEntry(VS_BOOL fScrollDisplay) {
    int inLeft,
    inTop,
    inRight,
    inBottom,
    inDummyRow;
    int inTermCharsPerRow;

    if (fScrollDisplay) {
        wherewin(&inLeft, &inTop, &inRight, &inBottom);

        inTermCharsPerRow = inGetRowLim();
        if (!obDisp.blActionFontASC8x21)
            vdCalculateCoord(GRID_4x8_TO_8x21, &inTermCharsPerRow, &inDummyRow);

        window(obDisp.inHomeCol, obDisp.inTopEntryRow, inTermCharsPerRow, obDisp.inCharsPerColumn);
        gotoxy(1, 1);
        delline();
        /* handle previously-entered value */
        if (obDisp.blNextLineCleanup) {
            //delline(); //LIEM, don't care just, just scroll 1x
            obDisp.blNextLineCleanup = VS_FALSE;
        }
        window(inLeft, inTop, inRight, inBottom);
    }
} /* end vdScrollDataEntry() */

/*-------------------------------------------------------------------------
    Function :    vdSetNextLineEntry
    Description : sets-up entry on next line for wide fields
    Returns :     
    Globals :
    Notes : 
    Modification History :
      #     Date      Who                     Description
    ----- -------- ---------- ---------------------------------------------
      0   08/25/98 EW_1       Creation 
--------------------------------------------------------------------------*/
void vdSetNextLineEntry() {
    obDisp.blEntryNextLine = VS_TRUE; /* entry value on line after prompt */
}

/*-------------------------------------------------------------------------
    Function :    vdClrNextLineEntry
    Description : sets-up entry on same line for fields
    Returns :     
    Globals :
    Notes : 
    Modification History :
      #     Date      Who                     Description
    ----- -------- ---------- ---------------------------------------------
      0   08/25/98 EW_1       Creation 
--------------------------------------------------------------------------*/
void vdClrNextLineEntry() {
    obDisp.blEntryNextLine = VS_FALSE;
}

/*-------------------------------------------------------------------------
    Function :    vdSetNextLineCleanup
    Description : Set Flag for Cleanup on multi-line entry fields
    Returns :     
    Globals :
    Notes : 
    Modification History :
      #     Date      Who                     Description
    ----- -------- ---------- ---------------------------------------------
      0   08/25/98 EW_1       Creation 
--------------------------------------------------------------------------*/
void vdSetNextLineCleanup() {
    obDisp.blNextLineCleanup = VS_TRUE;
}

/*-------------------------------------------------------------------------
    Function :    vdCleanupNxLine
    Description : clears out entry displayed on line following prompt
                  for entry routines which do not scroll...
    Returns :     
    Globals :
    Notes : 
    Modification History :
      #     Date      Who                     Description
    ----- -------- ---------- ---------------------------------------------
      0   08/25/98 EW_1       Creation 
--------------------------------------------------------------------------*/
void vdCleanupNxLine() {
    if (obDisp.blNextLineCleanup) {
        obDisp.blNextLineCleanup = VS_FALSE; 
        gotoxy(obDisp.inHomeCol, obDisp.inTopEntryRow);
        delline();
        delline();
    }
}

int UI_CODE_CHECK(char* a,char* b,short * c,char* d,unsigned char* e) {
    GET_VER(a, b, c, d, e);
    return 1;
}


#undef VSUI_C

